package com.engine4cloud.tdf.supervision.service.impl;

import com.engine4cloud.tdf.common.core.constant.enums.CorFileTypeEnum;
import com.engine4cloud.tdf.common.core.constant.enums.DictNameEnum;
import com.engine4cloud.tdf.common.core.exception.ValidateCodeException;
import com.engine4cloud.tdf.common.core.util.lambda.Actions;
import com.engine4cloud.tdf.common.security.service.TdfUser;
import com.engine4cloud.tdf.common.security.util.SecurityUtils;
import com.engine4cloud.tdf.supervision.convert.*;
import com.engine4cloud.tdf.supervision.dto.IdentityUniqueCheckDTO;
import com.engine4cloud.tdf.supervision.dto.query.DictCodeListQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxCrimeInfoQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxFileQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.DictSelectResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxCrimeInfoResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxFileResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxJudgmentResultDTO;
import com.engine4cloud.tdf.supervision.dto.create.TerminalRegistrationCreateDTO;
import com.engine4cloud.tdf.supervision.dto.result.TerminalBaseInfoResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.TerminalFamilySocietyResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.TerminalRegistrationResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.TerminalResumeResultDTO;
import com.engine4cloud.tdf.supervision.dto.update.TerminalBaseInfoUpdateDTO;
import com.engine4cloud.tdf.supervision.dto.update.TerminalRegistrationUpdateDTO;
import com.engine4cloud.tdf.supervision.entity.JzdxEntity;
import com.engine4cloud.tdf.supervision.entity.JzdxFamilySocietyEntity;
import com.engine4cloud.tdf.supervision.entity.JzdxJudgmentEntity;
import com.engine4cloud.tdf.supervision.entity.JzdxResumeEntity;
import com.engine4cloud.tdf.supervision.service.*;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Service
public class JzdxTerminalServiceImpl implements JzdxTerminalService {
    @Resource
    private JzdxService jzdxService;
    @Resource
    private JzdxCrimeInfoService crimeInfoService;
    @Resource
    private JzdxJudgmentService judgmentService;
    @Resource
    private JzdxFileService fileService;
    @Resource
    private JzdxIdentityCardService identityCardService;
    @Resource
    private JzdxBiologyFeatureService biologyFeatureService;
    @Resource
    private JzdxResumeService resumeService;
    @Resource
    private JzdxFamilySocietyService familySocietyService;
    @Resource
    private DictSelectService dictSelectService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String register(TerminalRegistrationCreateDTO dto) {
        Boolean unique = jzdxService.checkUniqueByIdentity(new IdentityUniqueCheckDTO(dto.getBaseInfo().getZjh()));
        if (!unique) {
            throw new ValidateCodeException("已报道登记");
        }

        TdfUser user = SecurityUtils.getUser();

        //保存身份证信息
        Actions.apply(Objects.nonNull(dto.getIdentityCard()), () -> identityCardService.create(dto.getIdentityCard()));

        //设置基本信息
        JzdxEntity entity = JzdxTerminalConvert.INSTANCE.create(dto.getBaseInfo(), user.getDeptId(), user.getTenantId());
        //设置人员编号
        entity.setRybh(jzdxService.initCorrectorCode(user.getDeptId()));
        jzdxService.save(entity);

        //保存判决信息
        judgmentService.save(JzdxTerminalJudgmentConvert.INSTANCE.create(dto.getBaseInfo(), entity.getRybh(), user.getTenantId()));

        //保存具体罪名和犯罪类型
        Actions.apply(Objects.nonNull(dto.getBaseInfo().getCrimeInfoList()),
                () -> crimeInfoService.saveBatchCrimeInfoList(JzdxCrimeInfoConvert.INSTANCE.create(entity, dto.getBaseInfo().getCrimeInfoList())));

        //保存照片信息
        Actions.apply(CollectionUtils.isNotEmpty(dto.getBaseInfo().getPhotoList()),
                () -> fileService.batchSaveFile(new JzdxFileQueryDTO(entity.getRybh(), CorFileTypeEnum.CORRECTOR_PHOTOGRAPH), dto.getBaseInfo().getPhotoList(), user));

        //保存生物特征信息
        Actions.apply(Objects.nonNull(dto.getBiology()), () -> biologyFeatureService.createOrUpdate(dto.getBiology()));

        //保存个人简历信息
        Actions.apply(CollectionUtils.isNotEmpty(dto.getResumeList()), () -> resumeService.createBatch(entity.getRybh(), dto.getResumeList().stream().map(r -> JzdxTerminalResumeConvert.INSTANCE.create(r, user.getTenantId())).toList()));

        //保存家庭社会关系信息
        Actions.apply(CollectionUtils.isNotEmpty(dto.getFamilyList()), () -> familySocietyService.createBatch(entity.getRybh(), dto.getFamilyList().stream().map(r -> JzdxTerminalFamilySocietyConvert.INSTANCE.create(r, user.getTenantId())).toList()));
        return entity.getRybh();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(TerminalRegistrationUpdateDTO dto) {
        JzdxEntity old = jzdxService.getByIdentityNotRelease(dto.getBaseInfo().getZjh());

        if (Objects.isNull(old)) {
            throw new ValidateCodeException("请先报道登记");
        }

        TdfUser user = SecurityUtils.getUser();
        //保存身份证信息
        Actions.apply(Objects.nonNull(dto.getIdentityCard()), () -> identityCardService.update(dto.getIdentityCard()));

        //更新基本信息
        jzdxService.updateById(JzdxTerminalConvert.INSTANCE.update(dto.getBaseInfo()));

        //更新判决信息
        this.updateJudgment(old.getRybh(), dto.getBaseInfo());

        //更新具体罪名和犯罪类型
        crimeInfoService.updateBatch(old, dto.getBaseInfo().getCrimeInfoList());

        //更新照片信息
        fileService.batchUpdateFile(new JzdxFileQueryDTO(old.getRybh(), CorFileTypeEnum.CORRECTOR_PHOTOGRAPH), dto.getBaseInfo().getPhotoList(), user);

        //更新生物特征信息
        Actions.apply(Objects.nonNull(dto.getBiology()), () -> biologyFeatureService.updateOrCreate(dto.getBiology()));

        //保存个人简历信息
        Actions.apply(CollectionUtils.isNotEmpty(dto.getResumeList()), () -> resumeService.updateBatch(old.getRybh(), dto.getResumeList().stream().map(r -> JzdxTerminalResumeConvert.INSTANCE.update(r)).toList()));

        //保存家庭社会关系信息
        Actions.apply(CollectionUtils.isNotEmpty(dto.getFamilyList()), () -> familySocietyService.updateBatch(old.getRybh(), dto.getFamilyList().stream().map(r -> JzdxTerminalFamilySocietyConvert.INSTANCE.update(r, user.getTenantId())).toList()));

        return true;
    }

    @Override
    public TerminalRegistrationResultDTO getByIdentity(String identity) {
        TerminalRegistrationResultDTO result = new TerminalRegistrationResultDTO();
        //查询矫正对象基本信息
        JzdxEntity dx = Optional.ofNullable(jzdxService.getByIdentityNotRelease(identity))
                .orElseThrow(() -> new ValidateCodeException("矫正对象数据不存在"));
        TerminalBaseInfoResultDTO baseInfo = JzdxTerminalConvert.INSTANCE.convert(dx);
        //设置判决信息
        this.setJudgment(baseInfo);
        //设置罪名
        this.setCrimeInfoList(baseInfo);
        //设置照片信息
        this.setPhotoList(baseInfo);
        //设置基本信息
        result.setBaseInfo(baseInfo);
        //设置身份证信息
        result.setIdentityCard(JzdxIdentityCardConvert.INSTANCE.convert(identityCardService.findOne(identity)));
        //设置生物特征信息
        result.setBiology(biologyFeatureService.findOne(baseInfo.getZjh()));
        //设置个人简历
        result.setResumeList(this.getResumeList(baseInfo.getRybh()));
        //设置家庭社会关系
        result.setFamilyList(this.getFamilySocietyList(baseInfo.getRybh()));

        return result;
    }

    private void setJudgment(TerminalBaseInfoResultDTO dto) {
        JzdxJudgmentResultDTO judgment = judgmentService.findByCode(dto.getRybh());
        Actions.apply(Objects.nonNull(judgment), () -> {
            dto.setFjx(judgment.getFjx());
            dto.setZyfzss(judgment.getZyfzss());
            dto.setSqjzqx(judgment.getSqjzqx());
            dto.setSqjzksrq(judgment.getSqjzksrq());
            dto.setSqjzjsrq(judgment.getSqjzjsrq());
        });
    }

    private void updateJudgment(String code, TerminalBaseInfoUpdateDTO dto) {
        JzdxJudgmentResultDTO result = judgmentService.findByCode(code);
        if (Objects.nonNull(result)) {
            JzdxJudgmentEntity entity = JzdxTerminalJudgmentConvert.INSTANCE.convert(result);
            entity.setFjx(dto.getFjx());
            entity.setZyfzss(dto.getZyfzss());
            entity.setSqjzqx(dto.getSqjzqx());
            entity.setSqjzksrq(dto.getSqjzksrq());
            entity.setSqjzjsrq(dto.getSqjzjsrq());
            judgmentService.updateById(entity);
        }
    }

    private List<TerminalResumeResultDTO> getResumeList(String code) {
        List<JzdxResumeEntity> entityList = resumeService.findByCode(code);
        if (CollectionUtils.isNotEmpty(entityList)) {
            //设置职务
            List<DictSelectResultDTO> dictJobList = dictSelectService.items(DictNameEnum.JOB.getType());
            return entityList.stream().map(entity -> JzdxTerminalResumeConvert.INSTANCE.convert(entity, dictJobList)).toList();
        }

        return Collections.emptyList();
    }

    private List<TerminalFamilySocietyResultDTO> getFamilySocietyList(String code) {
        List<JzdxFamilySocietyEntity> entityList = familySocietyService.findByCode(code);
        if (CollectionUtils.isNotEmpty(entityList)) {
            return entityList.stream().map(JzdxTerminalFamilySocietyConvert.INSTANCE::convert).toList();
        }

        return Collections.emptyList();
    }

    /**
     * 设置罪名
     *
     * @param dto dto
     */
    private void setCrimeInfoList(TerminalBaseInfoResultDTO dto) {
        List<JzdxCrimeInfoResultDTO> crimeInfoList = crimeInfoService.findList(new JzdxCrimeInfoQueryDTO(dto.getRybh()));
        if (CollectionUtils.isNotEmpty(crimeInfoList)) {
            List<String> categoryList = crimeInfoList.stream().map(JzdxCrimeInfoResultDTO::getFzlx).toList();
            List<DictSelectResultDTO> crimeNameList = dictSelectService.items(DictNameEnum.CRIMINAL_NAME.getType());
            List<DictSelectResultDTO> crimeTypeList = dictSelectService.items(new DictCodeListQueryDTO(categoryList, DictNameEnum.CRIMINAL_TYPE.getType()));
            //设置犯罪类型名称
            JzdxCrimeInfoConvert.INSTANCE.convertCrimeInfoList(crimeInfoList, crimeNameList, crimeTypeList);
            dto.setCrimeInfoList(crimeInfoList);
        }
    }

    private void setPhotoList(TerminalBaseInfoResultDTO dto) {
        List<JzdxFileResultDTO> photoList = fileService.findList(new JzdxFileQueryDTO(dto.getRybh(), CorFileTypeEnum.CORRECTOR_PHOTOGRAPH));
        dto.setPhotoList(photoList);
    }
}
